//! CDB 事务系统集成测试
//! 
//! 本文件包含对CDB事务系统的全面测试，验证ACID特性、并发控制、MVCC等功能

use cdb::storage::transaction::*;
use cdb::storage::page::PageManager;
use cdb::storage::tuple::RowId;
use std::sync::{Arc, Barrier};
use std::thread;
use std::time::Instant;
use tempfile::tempdir;

/// 创建测试用的事务管理器
fn create_test_transaction_manager() -> Result<Arc<TransactionManager>, cdb::Error> {
    let temp_dir = tempdir().map_err(|e| cdb::Error::storage(format!("创建临时目录失败: {}", e)))?;
    let wal_path = temp_dir.path().join("test.wal").to_string_lossy().to_string();
    let page_manager = Arc::new(PageManager::new(1000));
    
    TransactionManager::new(page_manager, wal_path)
        .map(Arc::new)
}

/// 测试基础事务操作
#[tokio::test]
async fn test_basic_transaction_operations() {
    let tx_manager = create_test_transaction_manager().unwrap();
    
    // 测试事务创建
    let tx = tx_manager.begin_transaction(IsolationLevel::ReadCommitted, false).unwrap();
    assert_eq!(*tx.status.read(), TransactionStatus::Active);
    assert!(!tx.read_only);
    
    // 测试事务提交
    tx_manager.commit_transaction(tx).unwrap();
    
    // 验证统计信息
    let stats = tx_manager.get_stats();
    assert_eq!(stats.total_transactions, 1);
    assert_eq!(stats.committed_transactions, 1);
    assert_eq!(stats.active_transactions, 0);
    
    println!("✅ 基础事务操作测试通过");
}

/// 测试事务回滚
#[tokio::test]
async fn test_transaction_rollback() {
    let tx_manager = create_test_transaction_manager().unwrap();
    
    // 创建事务并添加一些操作
    let tx = tx_manager.begin_transaction(IsolationLevel::ReadCommitted, false).unwrap();
    
    // 模拟写操作
    {
        let mut write_set = tx.write_set.write();
        write_set.insert(RowId::new(1, 100));
        write_set.insert(RowId::new(1, 101));
    }
    
    // 回滚事务
    tx_manager.rollback_transaction(tx).unwrap();
    
    // 验证统计信息
    let stats = tx_manager.get_stats();
    assert_eq!(stats.total_transactions, 1);
    assert_eq!(stats.rolled_back_transactions, 1);
    assert_eq!(stats.active_transactions, 0);
    
    println!("✅ 事务回滚测试通过");
}

/// 测试ACID原子性
#[tokio::test]
async fn test_acid_atomicity() {
    let tx_manager = create_test_transaction_manager().unwrap();
    
    // 测试1: 正常提交的事务应该全部生效
    let tx1 = tx_manager.begin_transaction(IsolationLevel::ReadCommitted, false).unwrap();
    
    // 模拟多个操作
    {
        let mut write_set = tx1.write_set.write();
        write_set.insert(RowId::new(1, 1));
        write_set.insert(RowId::new(1, 2));
        write_set.insert(RowId::new(1, 3));
    }
    
    // 提交事务
    tx_manager.commit_transaction(tx1).unwrap();
    
    // 验证事务已提交
    let stats = tx_manager.get_stats();
    assert_eq!(stats.committed_transactions, 1);
    
    // 测试2: 回滚的事务应该完全撤销
    let tx2 = tx_manager.begin_transaction(IsolationLevel::ReadCommitted, false).unwrap();
    
    {
        let mut write_set = tx2.write_set.write();
        write_set.insert(RowId::new(2, 1));
        write_set.insert(RowId::new(2, 2));
    }
    
    // 回滚事务
    tx_manager.rollback_transaction(tx2).unwrap();
    
    // 验证统计信息
    let final_stats = tx_manager.get_stats();
    assert_eq!(final_stats.committed_transactions, 1);
    assert_eq!(final_stats.rolled_back_transactions, 1);
    
    println!("✅ ACID原子性测试通过");
}

/// 测试ACID一致性
#[tokio::test]
async fn test_acid_consistency() {
    let tx_manager = create_test_transaction_manager().unwrap();
    
    // 模拟银行转账场景
    let tx = tx_manager.begin_transaction(IsolationLevel::ReadCommitted, false).unwrap();
    
    // 模拟账户余额检查和转账操作
    let initial_balance_a = 1000;
    let initial_balance_b = 500;
    let transfer_amount = 200;
    
    // 验证转账前后总金额保持不变（一致性约束）
    let final_balance_a = initial_balance_a - transfer_amount;
    let final_balance_b = initial_balance_b + transfer_amount;
    let total_before = initial_balance_a + initial_balance_b;
    let total_after = final_balance_a + final_balance_b;
    
    assert_eq!(total_before, total_after);
    
    // 模拟写操作
    {
        let mut write_set = tx.write_set.write();
        write_set.insert(RowId::new(3, 1)); // 账户A
        write_set.insert(RowId::new(3, 2)); // 账户B
    }
    
    // 提交事务
    tx_manager.commit_transaction(tx).unwrap();
    
    println!("✅ ACID一致性测试通过");
}

/// 测试ACID隔离性
#[tokio::test]
async fn test_acid_isolation() {
    let tx_manager = create_test_transaction_manager().unwrap();
    
    // 测试读已提交隔离级别
    let tx1 = tx_manager.begin_transaction(IsolationLevel::ReadCommitted, false).unwrap();
    let tx2 = tx_manager.begin_transaction(IsolationLevel::ReadCommitted, true).unwrap();
    
    // tx1修改数据但未提交
    {
        let mut write_set = tx1.write_set.write();
        write_set.insert(RowId::new(4, 200));
    }
    
    // tx2不应该读到未提交的数据
    // 验证快照时间戳
    assert!(tx2.snapshot_timestamp < tx1.id);
    
    tx_manager.commit_transaction(tx1).unwrap();
    tx_manager.commit_transaction(tx2).unwrap();
    
    println!("✅ ACID隔离性测试通过");
}

/// 测试ACID持久性
#[tokio::test]
async fn test_acid_durability() {
    let tx_manager = create_test_transaction_manager().unwrap();
    
    // 创建并提交一个事务
    let tx = tx_manager.begin_transaction(IsolationLevel::ReadCommitted, false).unwrap();
    
    // 模拟数据变更
    {
        let mut write_set = tx.write_set.write();
        write_set.insert(RowId::new(5, 300));
        write_set.insert(RowId::new(5, 301));
    }
    
    // 提交事务
    tx_manager.commit_transaction(tx).unwrap();
    
    // 强制刷新WAL以确保持久化
    tx_manager.flush_wal().unwrap();
    
    // 验证WAL中有记录
    let current_lsn = tx_manager.get_current_lsn();
    assert!(current_lsn > 0);
    
    // 验证事务已持久化
    let stats = tx_manager.get_stats();
    assert!(stats.committed_transactions > 0);
    
    println!("✅ ACID持久性测试通过");
}

/// 测试并发事务
#[tokio::test]
async fn test_concurrent_transactions() {
    let tx_manager = Arc::new(create_test_transaction_manager().unwrap());
    
    let num_threads = 4;
    let transactions_per_thread = 10;
    let barrier = Arc::new(Barrier::new(num_threads));
    
    let handles: Vec<_> = (0..num_threads).map(|thread_id| {
        let tx_manager = tx_manager.clone();
        let barrier = barrier.clone();
        
        thread::spawn(move || -> Result<(), cdb::Error> {
            // 等待所有线程准备就绪
            barrier.wait();
            
            for i in 0..transactions_per_thread {
                let tx = tx_manager.begin_transaction(IsolationLevel::ReadCommitted, false)?;
                
                // 模拟一些工作
                {
                    let mut write_set = tx.write_set.write();
                    write_set.insert(RowId::new(6, (thread_id * 1000 + i) as u16));
                }
                
                // 随机决定提交或回滚
                if i % 5 == 0 {
                    tx_manager.rollback_transaction(tx)?;
                } else {
                    tx_manager.commit_transaction(tx)?;
                }
            }
            
            Ok(())
        })
    }).collect();
    
    // 等待所有线程完成
    for handle in handles {
        handle.join().unwrap().unwrap();
    }
    
    // 验证统计信息
    let stats = tx_manager.get_stats();
    let total_expected = (num_threads * transactions_per_thread) as u64;
    assert_eq!(stats.total_transactions, total_expected);
    assert!(stats.committed_transactions > 0);
    assert!(stats.rolled_back_transactions > 0);
    assert_eq!(stats.active_transactions, 0);
    
    println!("✅ 并发事务测试通过");
}

/// 测试只读事务优化
#[tokio::test]
async fn test_readonly_transaction_optimization() {
    let tx_manager = create_test_transaction_manager().unwrap();

    // 创建只读事务
    let readonly_tx = tx_manager.begin_transaction(IsolationLevel::ReadCommitted, true).unwrap();
    assert!(readonly_tx.read_only);

    // 只读事务应该使用快照时间戳（可能为0，表示使用最大已提交事务ID）
    let snapshot_ts = readonly_tx.snapshot_timestamp;
    assert!(snapshot_ts >= 0); // 允许为0

    // 提交只读事务
    tx_manager.commit_transaction(readonly_tx).unwrap();

    // 验证统计信息
    let stats = tx_manager.get_stats();
    assert_eq!(stats.committed_transactions, 1);

    println!("✅ 只读事务优化测试通过");
}

/// 测试事务性能
#[tokio::test]
async fn test_transaction_performance() {
    let tx_manager = create_test_transaction_manager().unwrap();
    
    let num_transactions = 100;
    let start_time = Instant::now();
    
    // 测试事务吞吐量
    for _i in 0..num_transactions {
        let tx = tx_manager.begin_transaction(IsolationLevel::ReadCommitted, false).unwrap();
        tx_manager.commit_transaction(tx).unwrap();
    }
    
    let elapsed = start_time.elapsed();
    let throughput = num_transactions as f64 / elapsed.as_secs_f64();
    
    println!("📊 事务性能测试结果:");
    println!("  事务数量: {}", num_transactions);
    println!("  执行时间: {:?}", elapsed);
    println!("  吞吐量: {:.2} 事务/秒", throughput);
    
    // 基本性能要求：至少100 TPS
    assert!(throughput >= 100.0, "事务吞吐量过低: {:.2} TPS", throughput);
    
    // 验证统计信息
    let stats = tx_manager.get_stats();
    assert_eq!(stats.total_transactions, num_transactions as u64);
    assert_eq!(stats.committed_transactions, num_transactions as u64);
    assert_eq!(stats.active_transactions, 0);
    
    println!("✅ 事务性能测试通过");
}
